package com.server.thisService.controller.base;

import com.google.gson.reflect.TypeToken;
import com.project.annotation.common.MethodAuthority;
import com.project.annotation.enums.common.SuccessBaseCode;
import com.project.annotation.model.base.IdResult;
import com.project.annotation.model.base.PageResult;
import com.project.annotation.model.base.ResultBase;
import com.project.annotation.model.base.VoidResult;
import com.project.thisCommon.common.ConvertEntity;
import com.project.thisDatabase.base.model.BaseUpdateEntity;
import com.project.thisDatabase.base.model.EntityBase;
import com.project.thisDatabase.base.model.EntityPageBase;
import com.project.thisDatabase.base.model.entities.IntResultEntity;
import com.project.thisDatabase.base.model.entities.PageEntity;
import com.project.thisDatabase.base.service.ServiceInterfaceBase;
import com.server.mould.business.base.BaseCtrlInterface;
import com.server.mould.domain.reqeust.base.PageBaseRequest;
import com.server.mould.domain.reqeust.base.RequestValueBase;
import com.server.mould.domain.result.base.ResultValueBase;
import com.server.thisService.common.enums.ConstString;
import com.server.thisService.common.enums.SuccessCode;
import org.springframework.beans.factory.annotation.Autowired;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.TypeVariable;
import java.util.List;
import java.util.UUID;

public abstract class BaseController<
        T extends EntityBase,
        V extends RequestValueBase,
        X extends ResultValueBase,
        S extends ServiceInterfaceBase<T>> implements BaseCtrlInterface<V, X>  {

    @Autowired
    private S serviceInterface;

    @Override
    @MethodAuthority
    public ResultBase<List<X>> Search(V item) throws Exception {
        T query = EntityConvert(item);
        query.setStatus(ConstString.YES);

        return ResultBase.ok(serviceInterface.searchAut(query), SuccessBaseCode.SYSTEM_SUCCESS);
    }

    @Override
    @MethodAuthority
    public ResultBase<PageResult<X>> SearchPage(PageBaseRequest<V> item) throws Exception {
        PageResult<T> result = new PageResult<>();
        T query = EntityConvert(item.getData());
        query.setStatus(ConstString.YES);

        IntResultEntity count = serviceInterface.countAut(query);
        result.setCount(count.getResult());

        if (null == item.getPage()) {
            result.setRows(serviceInterface.searchAut(query));
        } else {
            EntityPageBase<T> page = ConvertPageEntity(item);
            result.setRows(serviceInterface.searchPageAut(page));
        }

        return ResultBase.ok(result, SuccessBaseCode.SYSTEM_SUCCESS);
    }

    @Override
    @MethodAuthority
    public ResultBase<Integer> Edit(V item) throws Exception {
        T query = EntityConvert(item);
        T cond = serviceInterface.setKeys(query);
        BaseUpdateEntity<T> update_en = new BaseUpdateEntity<>();
        update_en.setContent(query);
        update_en.setCondition(cond);
        cond.setStatus(ConstString.YES);
        Integer cnt = serviceInterface.updateSearchListAut(update_en);

        return ResultBase.ok(cnt, SuccessCode.SYSTEM_SUCCESS);
    }

    @Override
    @MethodAuthority
    public ResultBase<Integer> Add(V item) throws Exception {
        T find_en = EntityConvert(item);
        find_en.setStatus(ConstString.YES);
        Integer cnt = serviceInterface.insertAut(find_en);
        return ResultBase.ok(cnt, SuccessCode.SYSTEM_SUCCESS);
    }

    @Override
    @MethodAuthority
    public ResultBase<IdResult> Create(V item) throws Exception {
        IdResult res = new IdResult();
        T find_en = EntityConvert(item);
        find_en.setStatus(ConstString.YES);
        serviceInterface.insertAut(find_en);
        res.setId(find_en.getId());

        return ResultBase.ok(res, SuccessCode.SYSTEM_SUCCESS);
    }

    @Override
    @MethodAuthority
    public ResultBase<Integer> Delete(V item) throws Exception {
        T query = EntityConvert(item);
        BaseUpdateEntity<T> update_en = new BaseUpdateEntity<>();
        update_en.bindNone(query);
        update_en.getContent().setStatus(ConstString.NO);
        update_en.getContent().setDelCode(UUID.randomUUID().toString());
        Integer cnt = serviceInterface.updateSearchListAut(update_en);
        return ResultBase.ok(cnt, SuccessCode.SYSTEM_SUCCESS);
    }

    @Override
    @MethodAuthority
    public ResultBase<VoidResult> Change(V item) throws Exception {
        T find_en = EntityConvert(item);
        find_en.setStatus(ConstString.YES);
        serviceInterface.insertOrUpdate(find_en);
        return ResultBase.void_ok(SuccessCode.SYSTEM_SUCCESS);
    }

    @Override
    @MethodAuthority
    public ResultBase<List<X>> SearchInner(V item) throws Exception {
        T query = EntityConvert(item);
        query.setStatus(ConstString.YES);

        return ResultBase.ok(serviceInterface.search(query), SuccessBaseCode.SYSTEM_SUCCESS);
    }

    @Override
    @MethodAuthority
    public ResultBase<PageResult<X>> SearchPageInner(PageBaseRequest<V> item) throws Exception {
        PageResult<T> result = new PageResult<>();
        T query = EntityConvert(item.getData());
        query.setStatus(ConstString.YES);

        IntResultEntity count = serviceInterface.count(query);
        result.setCount(count.getResult());

        if (null == item.getPage()) {
            result.setRows(serviceInterface.search(query));
        } else {
            EntityPageBase<T> page = ConvertPageEntity(item);
            result.setRows(serviceInterface.searchPage(page));
        }

        return ResultBase.ok(result, SuccessBaseCode.SYSTEM_SUCCESS);
    }

    @Override
    @MethodAuthority
    public ResultBase<Integer> EditInner(V item) throws Exception {
        T query = EntityConvert(item);
        T cond = serviceInterface.setKeys(query);
        BaseUpdateEntity<T> update_en = new BaseUpdateEntity<>();
        update_en.setContent(query);
        update_en.setCondition(cond);
        cond.setStatus(ConstString.YES);
        Integer cnt = serviceInterface.updateSearchList(update_en);

        return ResultBase.ok(cnt, SuccessCode.SYSTEM_SUCCESS);
    }

    @Override
    @MethodAuthority
    public ResultBase<VoidResult> DeleteInner(V item) throws Exception {
        T query = EntityConvert(item);
        BaseUpdateEntity<T> update_en = new BaseUpdateEntity<>();
        update_en.bindNone(query);
        update_en.getContent().setStatus(ConstString.NO);
        update_en.getContent().setDelCode(UUID.randomUUID().toString());
        Integer cnt = serviceInterface.updateSearchList(update_en);
        return ResultBase.ok(cnt, SuccessCode.SYSTEM_SUCCESS);
    }

    public S getServiceInterface() {
        return serviceInterface;
    }

    public T EntityConvert(V item) throws Exception {
        Class cls = getClass();
        ParameterizedType superclass = (ParameterizedType)cls.getGenericSuperclass();
        Class type_cls = (Class)superclass.getActualTypeArguments()[0];
        T obj = (T)ConvertEntity.copyEntity(item, type_cls);
        return obj;
    }

    public EntityPageBase<T> ConvertPageEntity(PageBaseRequest<V> item) throws Exception {
        T obj = EntityConvert(item.getData());
        PageEntity page = ConvertEntity.copyEntity(item.getPage(), PageEntity.class);

        EntityPageBase<T> rtn = new EntityPageBase<>();
        rtn.setPageEntity(page);
        rtn.setData(obj);

        return rtn;
    }
}
